#ifndef __INIT_H__
#define __INIT_H__

#include <ntifs.h>

// macroses and constants
#define FileHidingFilterCDOName L"\\FileSystem\\Filters\\FileHidingFilterCDO"
#define FileHidingFilterPoolTag 'TPHF' //File Hiding Pool Tag

#define IS_DESIRED_DEVICE_TYPE(pDevice)                         \
    ((pDevice->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) ||   \
    (pDevice->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) ||  \
    (pDevice->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM))

#define IS_FILE_HIDING_FILTER_OBJECT(pDeviceObject)             \
    ((pDeviceObject != NULL) &&                                 \
    (pDeviceObject->DriverObject == GetFilterDriverObject()) && \
    (pDeviceObject->DeviceExtension != NULL))

#define COPY_FILTER_DEVICE_FLAGS(pTargetCDO, pNewFilterDeviceObject)                \
    if (BooleanFlagOn(pTargetCDO->Flags, DO_BUFFERED_IO))                           \
    {                                                                               \
        SetFlag(pNewFilterDeviceObject->Flags, DO_BUFFERED_IO);                     \
    }                                                                               \
                                                                                    \
    if (BooleanFlagOn(pTargetCDO->Flags, DO_DIRECT_IO))                             \
    {                                                                               \
        SetFlag(pNewFilterDeviceObject->Flags, DO_DIRECT_IO);                       \
    }                                                                               \
                                                                                    \
    if (BooleanFlagOn(pTargetCDO->Flags, DO_SUPPORTS_TRANSACTIONS))                 \
    {                                                                               \
        SetFlag(pNewFilterDeviceObject->Flags, DO_SUPPORTS_TRANSACTIONS);           \
    }                                                                               \
                                                                                    \
    if (BooleanFlagOn(pTargetCDO->Characteristics, FILE_DEVICE_SECURE_OPEN))        \
    {                                                                               \
        SetFlag(pNewFilterDeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN);  \
    }

// structures and types
typedef struct _FILE_HIDING_FILTER_DEVICE_EXTENSION
{
    PDEVICE_OBJECT pNextLowerDevice;

    struct
    {
        PDRIVER_DISPATCH pDispatchCreate;
        PDRIVER_DISPATCH pDispatchClose;
        PDRIVER_DISPATCH pDispatchDirectoryControl;
    } Dispatch;
}
FILE_HIDING_FILTER_DEVICE_EXTENSION, *PFILE_HIDING_FILTER_DEVICE_EXTENSION;

// routines
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath);

void FSNotificationCallback(IN PDEVICE_OBJECT pTargetCDO, IN BOOLEAN bFSActive);

// IRP dispatch routines
NTSTATUS FilterDispatchPassThrough(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIRP);

// get DRIVER_OBJECT
PDRIVER_OBJECT GetFilterDriverObject();

// return CDO and acquire internal lock
PDEVICE_OBJECT GetFilterCDOAndLock();

// release internal lock of CDO and make pointer invalid
void ReleaseFilterCDOAndUnlock(IN OUT PDEVICE_OBJECT* ppFilterCDO);

// create filter device
NTSTATUS CreateFilterDevice(const DEVICE_TYPE deviceType, PDEVICE_OBJECT* pNewFilterDevice);

#endif